Thoughts on "Composition Is More Important Than Inheritance"

Mark Leighton Fisher on 2007-03-02T17:58:24

First, thanks to all those who responded – I needed the input to help clarify my thoughts on this topic (see Composition Is More Important Than Inheritance to know what I am babbling about).

My point is that, whenever the subject turns to object-oriented programming, the examples always seem (IMHO) to feature inheritance and inheritance alone. Polymorphism is seen only as a useful side-effect of an inheritance-oriented design, while no attention is paid to (a) encapsulation, the basis for all O-O programming, and (b) other programming paradigms, even those conventionally seen in modern O-O programming like interfaces and allomorphism.

Like I have said, we have many tools in our toolbox, so we need to quit viewing the world as a set of nails to be hammered down. Looser coupling through message-passing instead of argument passing, like Alan Kay et.al. have advocated, is one approach likely to bear some exotically useful fruit. Personally, I have been working through Mark Jason Dominus's Higher-Order Perl, which reveals how techniques developed by LISP and functional programmers are of use to Perl programmers. For that matter, I was able last week to (manually) apply memoization to a VB6 routine thereby dropping the average execution time of the routine by 90%, so the lessons therein are not limited to Perl programmers.

As far as the software on CPAN goes, I am sure that just like my software, some of the designs could use improvement. However, my CPAN point was that the "things" in the solution domain do not all constitute a single, well-ordered tree (or even a forest of such trees). To me, solution domains instead resemble a mixed area, partly forested (high use of inheritance), but mostly a grassy plain with some trees scattered amongst the grasses. To stretch the metaphor past the breaking point, the methods (pun intended) for feeding horses and cattle (grasses/encapsulation) are necessarily different from the methods used in building country cabins (rule-based systems), which are different yet from the methods for maintaining fish and other water creatures (functional programming) (and so on). CPAN possesses a large subset of the infrastructure needed for building modern-day software, so (IMHO) it resembles the software engineering solution domain.

We have a large software engineering toolkit – let's use all of it rather than confining ourselves to the hammers and the screwdrivers. One way to explore the toolkit is to learn a language that is specialized for a certain solution domain. For example, it pays to learn regular expressions thoroughly, as no matter what problem domain you write programs for, you will still have to deal with a representation of your data and your program. Regular expressions make many problems in manipulating data&program representations (whether text, AST, or whatever) much more tractable (no surprise to Perl programmers).

Another solution set that is currently hot, Domain-Specific Languages, is actually just Little Languages all over again – DSLs owe much to the Unix Little Language tools YACC, eqn, pic, etc., which themselves owe much to the ease of building little languages when you have tools (like compiler-compilers) for easily building little languages. (YACC and its ilk represent an interesting case of bootstrapping.)

A software engineer's toolbox is so large that you may never explore the whole thing, even over the course of your whole career – but it pays and pays to explore the tools you need to make your programs faster, better, and cheaper. For example, if you have ever built a program to verify data, whether it is postal addresses, CAD data, or what-have-you, you have probably built some kind of expert system engine inside of the program. (This reminds of the quote about every large program having a badly-written Common LISP interpreter inside.)

Inheritance is not the only tool we have when composing programs (although it can be very useful). Perl 6 should be very interesting, as it brings (more of) the benefits of LISP and functional programming to a wider, conventional-syntax-using, audience. (Perl 5 already has closures, anonymous functions, (nearly) first-class-object regexes, along with the other functionality that enabled a not-too-wordy implementation (sic) for Higher-Order Perl.) As far as I know, Perl 6 will bring the most programming paradigms together under one roof of any mainstream language (and it seems to me to have a logical, consistent design to boot).

So, remember as you compose your programs – there are more notes than inheritance and more chord progressions than polymorphism in your program composition toolbox.